package com.hekewangzi.httpProxyClient.ui;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import com.hekewangzi.httpProxyClient.ProxyServerManager;
import java.io.*;
import java.util.Properties;
import com.formdev.flatlaf.FlatLightLaf;
import javax.swing.border.TitledBorder;

public class ProxyClientFrame extends JFrame {
    private JTextField localPortField;
    private JTextField serverIpField;
    private JTextField serverPortField;
    private JButton startButton;
    private JButton stopButton;
    private JTextArea logArea;
    private ProxyServerManager proxyServerManager;
    private static final String CONFIG_PATH = "src/main/resources/config.properties";

    static {
        try {
            UIManager.setLookAndFeel(new FlatLightLaf());
        } catch (Exception e) {
            System.err.println("FlatLaf 初始化失败，使用默认外观");
        }
    }

    public ProxyClientFrame() {
        setTitle("HttpProxyClient 可视化代理客户端");
        setSize(540, 480);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setResizable(true);
        getContentPane().setBackground(new Color(245, 247, 250));
        initUI();
        loadConfig();
    }

    private void initUI() {
        JLabel titleLabel = new JLabel("HttpProxyClient 代理客户端", JLabel.CENTER);
        titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 22));
        titleLabel.setBorder(BorderFactory.createEmptyBorder(18, 0, 10, 0));
        add(titleLabel, BorderLayout.NORTH);

        JPanel configPanel = new JPanel(new GridBagLayout());
        configPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(new Color(180, 200, 230)),
                "代理配置", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.BOLD, 14)));
        configPanel.setBackground(new Color(255, 255, 255));
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(8, 8, 8, 8);
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        configPanel.add(new JLabel("本地监听端口:"), gbc);
        // 输入框GridBagLayout权重修正
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        localPortField = new JTextField("4444", 18);
        localPortField.setToolTipText("本地代理监听端口");
        localPortField.setPreferredSize(new Dimension(160, 28));
        configPanel.add(localPortField, gbc);
        gbc.gridx = 0;
        gbc.gridy = 1;
        configPanel.add(new JLabel("目标服务器IP:"), gbc);
        gbc.gridx = 1;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        serverIpField = new JTextField("175.178.249.190", 18);
        serverIpField.setToolTipText("代理服务器IP地址");
        serverIpField.setPreferredSize(new Dimension(160, 28));
        configPanel.add(serverIpField, gbc);
        gbc.gridx = 0;
        gbc.gridy = 2;
        configPanel.add(new JLabel("目标服务器端口:"), gbc);
        gbc.gridx = 1;
        gbc.gridy = 2;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        serverPortField = new JTextField("6666", 18);
        serverPortField.setToolTipText("代理服务器端口");
        serverPortField.setPreferredSize(new Dimension(160, 28));
        configPanel.add(serverPortField, gbc);
        configPanel.setPreferredSize(new Dimension(400, 140));

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 24, 10));
        buttonPanel.setBackground(new Color(245, 247, 250));
        JButton saveButton = new JButton("💾 保存配置");
        saveButton.setFont(new Font("微软雅黑", Font.PLAIN, 13));
        saveButton.setBackground(new Color(33, 150, 243));
        saveButton.setForeground(Color.WHITE);
        saveButton.setFocusPainted(false);
        startButton = new JButton("\u25B6 启动代理");
        startButton.setFont(new Font("微软雅黑", Font.BOLD, 15));
        startButton.setBackground(new Color(76, 175, 80));
        startButton.setForeground(Color.WHITE);
        startButton.setFocusPainted(false);
        stopButton = new JButton("\u25A0 停止代理");
        stopButton.setFont(new Font("微软雅黑", Font.BOLD, 15));
        stopButton.setBackground(new Color(244, 67, 54));
        stopButton.setForeground(Color.WHITE);
        stopButton.setFocusPainted(false);
        stopButton.setEnabled(false);
        buttonPanel.add(saveButton);
        buttonPanel.add(startButton);
        buttonPanel.add(stopButton);
        // 主面板，垂直排列参数区和按钮区
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
        mainPanel.setBackground(new Color(245, 247, 250));
        mainPanel.add(configPanel);
        mainPanel.add(Box.createVerticalStrut(10));
        mainPanel.add(buttonPanel);
        mainPanel.setMinimumSize(new Dimension(300, 120));
        mainPanel.setPreferredSize(new Dimension(400, 160));

        logArea = new JTextArea();
        logArea.setEditable(false);
        logArea.setFont(new Font("Consolas", Font.PLAIN, 14));
        logArea.setBackground(new Color(245, 245, 245));
        logArea.setForeground(new Color(60, 60, 60));
        logArea.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
        JScrollPane logScroll = new JScrollPane(logArea);
        logScroll.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(new Color(180, 200, 230)),
                "运行日志", TitledBorder.LEFT, TitledBorder.TOP, new Font("微软雅黑", Font.BOLD, 14)));
        logScroll.setMinimumSize(new Dimension(300, 120));
        logScroll.setPreferredSize(new Dimension(400, 200));

        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, mainPanel, logScroll);
        splitPane.setResizeWeight(0.4); // 上下比例
        splitPane.setDividerSize(6);
        splitPane.setBorder(null);
        splitPane.setContinuousLayout(true);
        setLayout(new BorderLayout());
        add(titleLabel, BorderLayout.NORTH);
        add(splitPane, BorderLayout.CENTER);

        proxyServerManager = new ProxyServerManager();

        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int port = getLocalPort();
                String ip = getServerIp();
                int serverPort = getServerPort();
                if (isWindows()) {
                    configureWindowsProxy(port);
                } else {
                    configureMacProxy(port);
                }
                proxyServerManager.start(port, ip, serverPort, ProxyClientFrame.this::appendLog);
                appendLog("[INFO] 启动代理...");
                startButton.setEnabled(false);
                stopButton.setEnabled(true);
            }
        });
        stopButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                proxyServerManager.stop();
                if (isWindows()) {
                    disableWindowsProxy();
                } else {
                    disableMacProxy();
                }
                appendLog("[INFO] 停止代理");
                startButton.setEnabled(true);
                stopButton.setEnabled(false);
            }
        });
    }

    public int getLocalPort() {
        return Integer.parseInt(localPortField.getText().trim());
    }

    public String getServerIp() {
        return serverIpField.getText().trim();
    }

    public int getServerPort() {
        return Integer.parseInt(serverPortField.getText().trim());
    }

    public void appendLog(String msg) {
        logArea.append(msg + "\n");
        logArea.setCaretPosition(logArea.getDocument().getLength());
    }

    private void loadConfig() {
        Properties props = new Properties();
        try (InputStream in = new FileInputStream(CONFIG_PATH)) {
            props.load(in);
            localPortField.setText(props.getProperty("localPort", "4444"));
            serverIpField.setText(props.getProperty("serverIp", "175.178.249.190"));
            serverPortField.setText(props.getProperty("serverPort", "6666"));
            appendLog("[INFO] 配置已加载");
        } catch (IOException e) {
            appendLog("[WARN] 配置文件加载失败，使用默认值");
        }
    }

    private void saveConfig() {
        Properties props = new Properties();
        props.setProperty("localPort", localPortField.getText().trim());
        props.setProperty("serverIp", serverIpField.getText().trim());
        props.setProperty("serverPort", serverPortField.getText().trim());
        try (OutputStream out = new FileOutputStream(CONFIG_PATH)) {
            props.store(out, "HttpProxyClient 配置");
            appendLog("[INFO] 配置已保存");
        } catch (IOException e) {
            appendLog("[ERROR] 配置保存失败: " + e.getMessage());
        }
    }

    private boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().contains("win");
    }

    private void configureWindowsProxy(int port) {
        String proxy = "127.0.0.1:" + port;
        try {
            // 启用代理
            execAndLog(new String[] {
                    "reg", "add", "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
                    "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "1", "/f"
            });
            // 设置代理服务器
            execAndLog(new String[] {
                    "reg", "add", "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
                    "/v", "ProxyServer", "/d", proxy, "/f"
            });
            // 通知系统刷新代理设置（可选，部分系统不需要）
            execAndLog(new String[] {
                    "RunDll32.exe", "inetcpl.cpl,ProxyStub"
            });
            appendLog("[INFO] 已自动配置 Windows 系统代理: " + proxy);
        } catch (Exception ex) {
            appendLog("[ERROR] 配置 Windows 代理失败: " + ex.getMessage());
        }
    }
    private void disableWindowsProxy() {
        try {
            execAndLog(new String[] {
                    "reg", "add", "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
                    "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "0", "/f"
            });
            appendLog("[INFO] 已关闭 Windows 系统代理");
        } catch (Exception ex) {
            appendLog("[ERROR] 关闭 Windows 代理失败: " + ex.getMessage());
        }
    }


    private void disableMacProxy() {
        String networkService = getActiveWifiServiceName();
        try {
            execAndLog(new String[]{"/usr/sbin/networksetup", "-setwebproxystate", networkService, "off"});
            execAndLog(new String[]{"/usr/sbin/networksetup", "-setsecurewebproxystate", networkService, "off"});
            appendLog("[INFO] 已关闭 Mac 网页代理和安全网页代理 (服务名: " + networkService + ")");
        } catch (Exception ex) {
            appendLog("[ERROR] 关闭 Mac 代理失败: " + ex.getMessage());
        }
    }

    private void configureMacProxy(int port) {
        String networkService = getActiveWifiServiceName(); // 自动检测Wi-Fi服务名
        String proxyHost = "127.0.0.1";
        String portStr = String.valueOf(port);
        try {
            // 设置 HTTP 代理
            execAndLog(new String[] { "/usr/sbin/networksetup", "-setwebproxy", networkService, proxyHost, portStr });
            execAndLog(new String[] { "/usr/sbin/networksetup", "-setwebproxystate", networkService, "on" });
            // 设置 HTTPS 代理
            execAndLog(new String[] { "/usr/sbin/networksetup", "-setsecurewebproxy", networkService, proxyHost,
                    portStr });
            execAndLog(new String[] { "/usr/sbin/networksetup", "-setsecurewebproxystate", networkService, "on" });
            appendLog("[INFO] 已自动配置 Mac 网页代理和安全网页代理 (服务名: " + networkService + ")");
        } catch (Exception ex) {
            appendLog("[ERROR] 配置 Mac 代理失败: " + ex.getMessage());
        }
    }

    private void execAndLog(String[] cmd) throws IOException, InterruptedException {
        Process p = Runtime.getRuntime().exec(cmd);
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
        BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        String s;
        StringBuilder output = new StringBuilder();
        while ((s = stdInput.readLine()) != null)
            output.append(s).append("\n");
        while ((s = stdError.readLine()) != null)
            output.append(s).append("\n");
        int exitCode = p.waitFor();
        appendLog("[CMD] " + String.join(" ", cmd) + " [exit=" + exitCode + "]");
        if (output.length() > 0)
            appendLog("[CMD OUTPUT] " + output.toString());
    }

    /**
     * 自动检测当前活跃的 Wi-Fi 服务名（networksetup 的服务名）
     */
    private String getActiveWifiServiceName() {
        try {
            // 获取所有服务名
            Process listServices = Runtime.getRuntime()
                    .exec(new String[] { "/usr/sbin/networksetup", "-listallnetworkservices" });
            BufferedReader reader = new BufferedReader(new InputStreamReader(listServices.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                // 跳过第一行（可能是警告）
                if (line.trim().isEmpty() || line.contains("An asterisk"))
                    continue;
                // 常见Wi-Fi服务名
                if (line.contains("Wi-Fi") || line.contains("无线网络") || line.contains("AirPort")) {
                    return line.trim();
                }
            }
        } catch (Exception e) {
            appendLog("[ERROR] 检查Wi-Fi服务名失败: " + e.getMessage());
        }
        // 默认返回 Wi-Fi
        return "Wi-Fi";
    }
}